import { Client, Socket } from "@heroiclabs/nakama-js";
import { v4 as uuidv4 } from "uuid";
import { OpCode } from "./messages";
import { I_gameData } from "./playerInfo";

class Nakama {
    client: Client;
    session: any;
    socket: Socket;
    matchID: any;
    connected: boolean;

    handlers: { [cmdIndex: number]: Function } = {};
    bindedObj: { [cmdIndex: number]: any } = {};
    route: string[] = [];

    constructor() {
        this.client = null!;
        this.session
        this.socket // ep4
        this.matchID // ep4
        this.connected = false;
    }

    async authenticate(username: string, id: string) {
        // this.client = new Client("defaultkey", "192.168.10.15", "7350");
        this.client = new Client("defaultkey", "localhost", "7350");
        // this.client.ssl = false;

        // let deviceId = localStorage.getItem("deviceId");
        // if (!deviceId) {
        //     deviceId = uuidv4();
        //     localStorage.setItem("deviceId", deviceId);
        // }
        // console.log("device:" + deviceId);
        // this.session = await this.client.authenticateDevice(deviceId, true);
        this.session = await this.client.authenticateCustom("custom-" + id, true, username);
        console.log('user_id = ' + this.session.user_id);
        localStorage.setItem("user_id", this.session.user_id);

        // ep4
        const trace = false;
        this.socket = this.client.createSocket();
        let session = await this.socket.connect(this.session, false);
        console.log('session = ' + session)
        this.connected = true

        this.socket.onmatchdata = (result) => {
            // console.log("onmatchdata result:" + JSON.stringify(result));
            let text = new TextDecoder().decode(result.data)
            let data = null
            if (text) data = JSON.parse(text)
            // console.log("onmatchdata" + JSON.stringify(data));
            let op_code = result.op_code;
            if (this.handlers[op_code]) {
                this.handlers[op_code](data);
            }

            // switch (result.op_code) {
            //     case 1:
            //         this.gameStarted = true;
            //         this.svr_matchBack({code: result.op_code});
            //         this.svr_onGameStart(data);
            //         break;
                
            //     case 3:
            //         this.svr_matchBack({code: result.op_code});
            //         break;
                
            
            // }
        };

    }
    useSSL(useSSL: any, trace: boolean): any {
        throw new Error("Method not implemented.");
    }

    isConnected() {
        return this.isConnected
    }

    async findMatch() { // ep4
        const rpcid = "find_match_js";
        const matches: any = await this.client.rpc(this.session, rpcid, {});

        this.matchID = matches.payload.matchIds[0]
        await this.socket.joinMatch(this.matchID);
        // await this.socket.leaveMatch(this.matchID);
        console.log("Matched joined!")
    }

    async quitMatch() { // ep4
        if (this.matchID) {
            await this.socket.leaveMatch(this.matchID);
            this.matchID = null;
            console.log("Matched quit!")
        }
    }

    /**
     * 创建联赛
     */
    async createTournament() { // ep4
        const rpcid = "create_tournament_js";
        const tournament: any = await this.client.rpc(this.session, rpcid, {});
        
        console.log("Created tournament!" + JSON.stringify(tournament));
        // this.matchID = matches.payload.matchIds[0]
        // await this.socket.joinMatch(this.matchID);
        // // await this.socket.leaveMatch(this.matchID);
        console.log("Created tournament!")
        return tournament
    }


    async makeMove(index) { // ep4
        var data = { "position": index };
        await this.socket.sendMatchState(this.matchID, 4, JSON.stringify(data));
        console.log("Match data sent")
    }

    /**
     * 
     * @param ids 出牌
     */
    async playCards(ids: number[]) { // ep4
        // var data = { "position": index };
        await this.socket.sendMatchState(this.matchID, OpCode.PLAY, JSON.stringify(ids));
        console.log("Match data sent: " + JSON.stringify(ids))
    }

    addHandler(op_code: number, cb: (msg?: any) => void, self: any) {
        
        this.handlers[op_code] = cb.bind(self);
        this.bindedObj[op_code] = self;
    }

    removeThisHandlers(self: any) {
        for (let index in this.bindedObj) {
            if (this.bindedObj[index] === self) {
                delete this.bindedObj[index];
                delete this.handlers[index];
            }
        }
    }
}

export default new Nakama()